home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.0 SDK / Sample Code / SortPictsMP ƒ / CopyBlits ƒ / CopyBlits.c next >
Encoding:
Text File  |  1999-08-03  |  12.0 KB  |  479 lines  |  [TEXT/CWIE]

  1. /**\
  2. |**|    CopyBlits.c
  3. \**/
  4.  
  5. // compiler directives
  6. #define USE_SMP 1
  7.  
  8. // includes
  9. #include "CopyBlits.h"
  10.  
  11. // typdef's, defines, enums, etc.
  12. #if USE_SMP
  13. #    define GETPIXBASEADDR(h) ((*h)->baseAddr)
  14. #    define DO_LOCKING 0    // Must be zero for MP
  15. #else
  16. #    define GETPIXBASEADDR(h) GetPixBaseAddr(h)
  17. #    define DO_LOCKING 0
  18. #endif
  19.  
  20. // local (static) variables
  21. static CTabHandle gCTabHandle = nil;
  22. static UInt16 gCTab16[256];
  23. static UInt32 gCTab32[256];
  24.  
  25. // implementation
  26.  
  27. // Save color translation table
  28. void Set_ColorTable(CTabHandle pCTabHandle)
  29. {
  30.     if (gCTabHandle != pCTabHandle)
  31.     {
  32.         gCTabHandle = pCTabHandle;
  33.         if (pCTabHandle)
  34.         {
  35.             if ((*pCTabHandle)->ctSize >= 255)
  36.             {
  37.                 short index;
  38.                 for (index = 0;index < 256;index++)
  39.                 {
  40.                     RGBColor tRGBColor = (**pCTabHandle).ctTable[index].rgb;
  41.                     gCTab32[index] =     ((tRGBColor.red >> 8) << 16) +
  42.                                         ((tRGBColor.green >> 8) << 8) +
  43.                                         ((tRGBColor.blue >> 8) << 0);
  44.                     gCTab16[index] =     ((tRGBColor.red >> 11) << 10) +
  45.                                         ((tRGBColor.green >> 11) << 5) +
  46.                                         ((tRGBColor.blue >> 11) << 0);
  47.                 }
  48.             }
  49.         }
  50.     }
  51. }
  52.  
  53. // Generic routine that uses pixel size to determ which optimized routine to use
  54. // If you KNOW your depth you should call the approate routine yourself and skip
  55. // the subroutine/switch overhead.
  56.  
  57. void CopyBlits(    const PixMapHandle srcPixMapHdl,
  58.                 const PixMapHandle dstPixMapHdl,
  59.                 const Rect *srcRect,
  60.                 const Rect *dstRect
  61. )
  62. {
  63.     if ((*srcPixMapHdl)->pixelSize == 8)
  64.     {
  65.         switch ((*dstPixMapHdl)->pixelSize)
  66.         {
  67.             case    8:
  68. //                CopyBlits8(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);    // old
  69.                 CopyBlits8_8(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  70.                 break;
  71.             case    16:
  72.                 CopyBlits8_16(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  73.                 break;
  74.             case    32:
  75.                 CopyBlits8_32(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  76.                 break;
  77.             default:
  78. #if !USE_SMP
  79.                 CopyBits((BitMap*) *srcPixMapHdl,(BitMap*) *dstPixMapHdl,srcRect,dstRect,0,nil);
  80. #endif USE_SMP
  81.                 break;
  82.         }
  83.     }
  84. #if !USE_SMP
  85.     else
  86.         CopyBits((BitMap*) *srcPixMapHdl,(BitMap*) *dstPixMapHdl,srcRect,dstRect,0,nil);
  87. #endif USE_SMP
  88. }
  89.  
  90. // This is one of the first non-asm blitters I ever saw. Not as fast as CopyBlits8_8 but I left
  91. // it in just to show you the skanky nested switch/while code (see Duff's device). ewueee!
  92. // (194 fps vs. 300 fps CopyBits)
  93. void CopyBlits8    (    const PixMapHandle srcPixMapHdl,
  94.                     const PixMapHandle dstPixMapHdl,
  95.                     const Rect *srcRect,
  96.                     const Rect *dstRect
  97. )
  98. {
  99.     UInt32            dstLeft,dstRight;
  100.     UInt32            *srcRow,*dstRow;
  101.     register UInt32    *srcPtr,*dstPtr;
  102.     UInt32            leftMask,rightMask;
  103.     UInt32            notLeftMask,notRightMask;
  104.  
  105.     UInt32            srcRowBytes;
  106.     UInt32            dstRowBytes;
  107.     UInt32            srcLeft;
  108.  
  109.     UInt32            dstLong;
  110.     UInt32            dstLongs;
  111.     UInt32            height;
  112.     UInt32            offset;
  113.     UInt32            timesCopy;
  114.  
  115.     // This assumes that the pixmap is already locked
  116.     srcRow = (UInt32 *) (*srcPixMapHdl)->baseAddr;
  117.     dstRow = (UInt32 *) (*dstPixMapHdl)->baseAddr;
  118.     
  119.     // get the bit offset to the src left edge
  120.     srcLeft = (srcRect->left - (*srcPixMapHdl)->bounds.left) * (*srcPixMapHdl)->pixelSize;
  121.         
  122.     // offset the src ptr to the first long
  123.     srcRow += srcLeft >> 5;
  124.     
  125.     // get the bit offset to the dst left and right edges
  126.     dstLeft = (dstRect->left - (*dstPixMapHdl)->bounds.left) * (*dstPixMapHdl)->pixelSize;
  127.     dstRight = (dstRect->right - (*dstPixMapHdl)->bounds.left) * (*dstPixMapHdl)->pixelSize;
  128.     
  129.     // get the number of middle longs to do minus the left edge long
  130.     dstLongs = ((dstRight - dstLeft) >> 5) - 1;
  131.     
  132.     // offset the dst Ptr to the first long
  133.     dstRow += dstLeft >> 5;
  134.  
  135.     // now compute left and right masks for the dst
  136.     dstLeft &= 0x1f;
  137.     leftMask = ( 1 << dstLeft ) - 1;
  138.     notLeftMask = ~leftMask;
  139.     
  140.     dstRight &= 0x1f;
  141.     notRightMask = ( 1 << dstRight ) - 1;
  142.     rightMask = ~notRightMask;
  143.     
  144.     srcRowBytes = (*srcPixMapHdl)->rowBytes & 0x3fff;
  145.     dstRowBytes = (*dstPixMapHdl)->rowBytes & 0x3fff;
  146.  
  147.     // offset the src and dst ptrs to the first row
  148.     offset = (srcRect->top - (*srcPixMapHdl)->bounds.top) * srcRowBytes;
  149.     srcRow = (UInt32*) ((Ptr) srcRow + offset);
  150.  
  151.     offset = (dstRect->top - (*dstPixMapHdl)->bounds.top) * dstRowBytes;
  152.     dstRow = (UInt32*) ((Ptr) dstRow + offset);
  153.  
  154.     /* check if we need to do the left and right mask */
  155.     if ( leftMask )
  156.     {
  157.         if ( notLeftMask == 0 )
  158.         {
  159.             leftMask = 0;
  160.             dstLongs++;
  161.         }
  162.     }
  163.         
  164.     if ( rightMask )
  165.     {
  166.         if ( notRightMask == 0 )
  167.         {
  168.             rightMask = 0;
  169.             dstLongs++;
  170.         }
  171.     }
  172.  
  173.     height = srcRect->bottom - srcRect->top;    // No scaling allowed
  174.  
  175.     //for ( ; height >= 0; --height )
  176.     // changing the above 'for()' to the below 'while()' is what made this blit routine
  177.     // faster than CopyBits - a speed improvement equal to all other changes I had made
  178.     // previously.  (about 4 to 5 milliseconds, in case you were wondering)
  179.     // Lesson: the true bottlenecks are not always the obvious ones
  180.     while (height--)
  181.     {
  182.         srcPtr = srcRow;
  183.         dstPtr = dstRow;
  184.         
  185.         /* do the masked left edge */
  186.         if ( leftMask )
  187.         {
  188.             dstLong = *srcPtr++ & leftMask;
  189.             dstLong |= *dstPtr & notLeftMask;
  190.             *dstPtr++ = dstLong;
  191.         }
  192.  
  193.         /* do the middle longs with Duff's device */
  194.         timesCopy = (dstLongs + 15) >> 4;
  195.         
  196.         switch( dstLongs & 0xF )
  197.         {
  198.             case 0:    do
  199.                 {    *dstPtr++ = *srcPtr++;
  200.             case 15:    *dstPtr++ = *srcPtr++;
  201.             case 14:    *dstPtr++ = *srcPtr++;
  202.             case 13:    *dstPtr++ = *srcPtr++;
  203.             case 12:    *dstPtr++ = *srcPtr++;
  204.             case 11:    *dstPtr++ = *srcPtr++;
  205.             case 10:    *dstPtr++ = *srcPtr++;
  206.             case 9:        *dstPtr++ = *srcPtr++;
  207.             case 8:        *dstPtr++ = *srcPtr++;
  208.             case 7:        *dstPtr++ = *srcPtr++;
  209.             case 6:        *dstPtr++ = *srcPtr++;
  210.             case 5:        *dstPtr++ = *srcPtr++;
  211.             case 4:        *dstPtr++ = *srcPtr++;
  212.             case 3:        *dstPtr++ = *srcPtr++;
  213.             case 2:        *dstPtr++ = *srcPtr++;
  214.             case 1:        *dstPtr++ = *srcPtr++;
  215.                 } while( --timesCopy > 0 );
  216.         }
  217.  
  218.         /* do the masked right edge */
  219.         if ( rightMask )
  220.         {
  221.             dstLong = *srcPtr & rightMask;
  222.             dstLong |= *dstPtr & notRightMask;
  223.             *dstPtr = dstLong;
  224.         }
  225.         
  226.         /* bump to the next row */
  227.         srcRow = (UInt32*) ((Ptr) srcRow + srcRowBytes);
  228.         dstRow = (UInt32*) ((Ptr) dstRow + dstRowBytes);
  229.     }
  230. }
  231.  
  232. // my Fastest (non-asm) 8 to 8 bit blitter
  233. // (354 fps vs. 300 fps CopyBits)
  234. void CopyBlits8_8    (    const PixMapHandle srcPixMapHdl,
  235.                         const PixMapHandle dstPixMapHdl,
  236.                         const Rect *srcRect,
  237.                         const Rect *dstRect
  238. )
  239. {
  240.     UInt32    doubleCount,count;
  241.     UInt32    startFlags, endFlags;
  242.     UInt8    *src, *dst;
  243.     UInt32    srcSkip, dstSkip;
  244.     UInt32    width,height;
  245.  
  246.     width = srcRect->right - srcRect->left;
  247.     height = srcRect->bottom - srcRect->top;
  248.  
  249.     if (!width || !height)
  250.         return;    // nothing to copy!
  251.  
  252. #if DO_LOCKING
  253.     {
  254.         GWorldFlags srcGWFlags = GetPixelsState(srcPixMapHdl);
  255.         GWorldFlags dstGWFlags = GetPixelsState(dstPixMapHdl);
  256.  
  257.         if (0 == (srcGWFlags & pixelsLocked))    // if source not locked
  258.             if (!LockPixels(srcPixMapHdl))        // and we can't lock it
  259.                 return;    // give up
  260.  
  261.         if (0 == (dstGWFlags & pixelsLocked))    // if dest not locked
  262.             if (!LockPixels(dstPixMapHdl))        // and we can't lock it
  263.                 goto unlock;
  264. #endif
  265.  
  266.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  267.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  268.  
  269.     src = (UInt8*) GETPIXBASEADDR(srcPixMapHdl) +
  270.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  271.         srcRect->left - (*srcPixMapHdl)->bounds.left;
  272.     dst = (UInt8*) GETPIXBASEADDR(dstPixMapHdl) +
  273.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  274.         dstRect->left - (*dstPixMapHdl)->bounds.left;
  275.  
  276.     startFlags = ((UInt8 *) (((UInt32) src + 7U) & ~7U)) - src;
  277.     endFlags = ((UInt32) (src + width)) & 7U;
  278.     doubleCount = ((width - startFlags) - endFlags) / 8;
  279.  
  280.     // pre-fix skip values
  281.     srcSkip -= width;
  282.     dstSkip -= width;
  283.  
  284.     while (height--)
  285.     {
  286.         if (startFlags & 1)    // byte align
  287.             *dst++ = *src++;
  288.  
  289.         if (startFlags & 2)    // word align
  290.         {
  291.             *(UInt16*) dst = *(UInt16*) src;
  292.             src += 2;
  293.             dst += 2;
  294.         }
  295.  
  296.         if (startFlags & 4)    // long align
  297.         {
  298.             *(UInt32*) dst = *(UInt32*) src;
  299.             src += 4;
  300.             dst += 4;
  301.         }
  302.  
  303.         // copy doubles
  304.         for (count = 0; count < doubleCount; count++)
  305.         {
  306.             *(double*) dst = *(double*) src;
  307.             src += 8;
  308.             dst += 8;
  309.         }
  310.  
  311.         // copy remaining long
  312.         if (endFlags & 4)
  313.         {
  314.             *(UInt32*) dst = *(UInt32*) src;
  315.             src += 4;
  316.             dst += 4;
  317.         }
  318.             
  319.         // copy remaining word
  320.         if (endFlags & 2)
  321.         {
  322.             *(UInt16*) dst = *(UInt16*) src;
  323.             src += 2;
  324.             dst += 2;
  325.         }
  326.  
  327.         // copy remaining byte
  328.         if (endFlags & 1)
  329.             *dst++ = *src++;
  330.  
  331.         src += srcSkip;
  332.         dst += dstSkip;
  333.     }
  334. #if DO_LOCKING
  335. unlock:
  336.         if (0 == (srcGWFlags & pixelsLocked))    // if source wasn't locked
  337.             UnlockPixels(srcPixMapHdl);            // unlock it
  338.         if (0 == (dstGWFlags & pixelsLocked))    // if dest wasn't locked
  339.             UnlockPixels(dstPixMapHdl);            // unlock it
  340.     }
  341. #endif
  342. }
  343.  
  344. // my Fastest (non-asm) 8 to 16 bit blitter
  345. // (50 fps vs. 42 fps CopyBits)
  346. void CopyBlits8_16    (    const PixMapHandle srcPixMapHdl,
  347.                         const PixMapHandle dstPixMapHdl,
  348.                         const Rect *srcRect,
  349.                         const Rect *dstRect
  350. )
  351. {
  352.     UInt8    *src;
  353.     UInt16    *dst;
  354.     UInt32    count;
  355.     UInt32    srcSkip, dstSkip;
  356.     UInt32    width,height;
  357.  
  358.     Set_ColorTable((**srcPixMapHdl).pmTable);
  359.  
  360.     width = srcRect->right - srcRect->left;
  361.     height = srcRect->bottom - srcRect->top;
  362.  
  363.     if (!width || !height)
  364.         return;
  365.  
  366. #if DO_LOCKING
  367.     {
  368.         GWorldFlags srcGWFlags = GetPixelsState(srcPixMapHdl);
  369.         GWorldFlags dstGWFlags = GetPixelsState(dstPixMapHdl);
  370.  
  371.         if (0 == (srcGWFlags & pixelsLocked))    // if source not locked
  372.             if (!LockPixels(srcPixMapHdl))        // and we can't lock it
  373.                 return;    // give up
  374.  
  375.         if (0 == (dstGWFlags & pixelsLocked))    // if dest not locked
  376.             if (!LockPixels(dstPixMapHdl))        // and we can't lock it
  377.                 goto unlock;
  378. #endif
  379.  
  380.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  381.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  382.  
  383.     src = (UInt8*) (GETPIXBASEADDR(srcPixMapHdl) +
  384.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  385.         srcRect->left - (*srcPixMapHdl)->bounds.left);
  386.     dst = (UInt16*) (GETPIXBASEADDR(dstPixMapHdl) +
  387.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  388.         ((dstRect->left - (*dstPixMapHdl)->bounds.left) << 1));
  389.  
  390.     // pre-fix skip values
  391.     srcSkip -= width;
  392.     dstSkip -= width << 1;
  393.  
  394.     while (height--)
  395.     {
  396.         for (count = 0; count < width; count++)
  397.             *dst++ = gCTab16[*src++];
  398.         src += srcSkip;
  399.         dst = (UInt16*) (dstSkip + (Ptr) dst);
  400.     }
  401.  
  402. #if DO_LOCKING
  403. unlock:
  404.         if (0 == (srcGWFlags & pixelsLocked))    // if source wasn't locked
  405.             UnlockPixels(srcPixMapHdl);            // unlock it
  406.         if (0 == (dstGWFlags & pixelsLocked))    // if dest wasn't locked
  407.             UnlockPixels(dstPixMapHdl);            // unlock it
  408.     }
  409. #endif
  410. }
  411.  
  412. // my Fastest (non-asm) 8 to 32 bit blitter
  413. // (50 fps vs. 39 fps CopyBits)
  414. void CopyBlits8_32    (    const PixMapHandle srcPixMapHdl,
  415.                         const PixMapHandle dstPixMapHdl,
  416.                         const Rect *srcRect,
  417.                         const Rect *dstRect
  418. )
  419. {
  420.     register    UInt8    *src;
  421.     register    UInt32    *dst;
  422.     register    UInt32    count;
  423.     register    UInt32    srcSkip, dstSkip;
  424.     register    UInt32    width,height;
  425.  
  426.     Set_ColorTable((**srcPixMapHdl).pmTable);
  427.  
  428.     width = srcRect->right - srcRect->left;
  429.     height = srcRect->bottom - srcRect->top;
  430.  
  431.     if (!width || !height)
  432.         return;
  433.  
  434. #if DO_LOCKING
  435.     {
  436.         GWorldFlags srcGWFlags = GetPixelsState(srcPixMapHdl);
  437.         GWorldFlags dstGWFlags = GetPixelsState(dstPixMapHdl);
  438.  
  439.         if (0 == (srcGWFlags & pixelsLocked))    // if source not locked
  440.             if (!LockPixels(srcPixMapHdl))        // and we can't lock it
  441.                 return;    // give up
  442.  
  443.         if (0 == (dstGWFlags & pixelsLocked))    // if dest not locked
  444.             if (!LockPixels(dstPixMapHdl))        // and we can't lock it
  445.                 goto unlock;
  446. #endif
  447.  
  448.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  449.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  450.  
  451.     src = (UInt8*) (GETPIXBASEADDR(srcPixMapHdl) +
  452.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  453.         srcRect->left - (*srcPixMapHdl)->bounds.left);
  454.     dst = (UInt32*) (GETPIXBASEADDR(dstPixMapHdl) +
  455.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  456.         ((dstRect->left - (*dstPixMapHdl)->bounds.left) << 2));
  457.  
  458.     // pre-fix skip values
  459.     srcSkip -= width;
  460.     dstSkip -= width << 2;
  461.  
  462.     while (height--)
  463.     {
  464.         for (count = 0; count < width; count++)
  465.             *dst++ = gCTab32[*src++];
  466.         src += srcSkip;
  467.         dst = (UInt32*) (dstSkip + (Ptr) dst);
  468.     }
  469.  
  470. #if DO_LOCKING
  471. unlock:
  472.         if (0 == (srcGWFlags & pixelsLocked))    // if source wasn't locked
  473.             UnlockPixels(srcPixMapHdl);            // unlock it
  474.         if (0 == (dstGWFlags & pixelsLocked))    // if dest wasn't locked
  475.             UnlockPixels(dstPixMapHdl);            // unlock it
  476.     }
  477. #endif
  478. }
  479.